/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "空间分割.h"

#include <节点/插座/通用插座.h>

#include <节点/插座/C_单值矢量插座.h>
#include <节点/插座/list/list物体插座.h>
#include <节点/插座/list/list矢量插座.h>

#include "Context/数据转换.h"

#include <Context/当前默认操作数据.h>
#include <Context/数据创建销毁.h>






C_点距八叉树节点::C_点距八叉树节点(S_设备环境& ctx) : C_节点基类("点距八叉树节点") {
	m_Name = L"点距八叉树节点";
	m_GPU环境 = ctx;

	auto* 网格 = f_surface_创建网格对象(nullptr, m_GPU环境, E_网格数据枚举::e_Mesh_VULKAN);
	m_Ob = f_ob_创建物体(m_GPU环境, E_物体类型::t_网格);
	f_ob_set数据槽数量(m_Ob, 1);
	f_ob_set数据(m_Ob, 网格, 0);
	f_ob_set材质(m_Ob, f_NodeCtx_get单色点材质());
	
	//f_NodeCtx_get默认场景()->f_add物体(m_Ob, E_场景物体容器类型::e_集合);

	


	C_插座基类* socket;
	DEF_创建引用插座_I(L"点");
	DEF_创建F32插座_v1_I(L"最小单元距离");
	DEF_创建Vec3插座_v1_I(L"域大小");
	DEF_创建Vec3插座_v1_I(L"域偏移");

	DEF_创建点距八叉树插座_O(L"树");


	S_点距八叉树* t = f_空间划分_create球形八叉树(100000.0);
	f_get输出插座(1)->f_setData(t);

	float32 半径 = 0.5;
	f_get输入插座(2)->f_setData(&半径);

	vec3 域大小 = {};
	f_get输入插座(4)->f_setData(&域大小);
	域大小 = {512, 512, 512};
	f_get输入插座(3)->f_setData(&域大小);
}

C_点距八叉树节点::~C_点距八叉树节点() {
	f_空间划分_destroy球形八叉树((S_点距八叉树*)f_get输出插座(1)->f_getData(0));
}

bool C_点距八叉树节点::f_update() {
	auto& 输入数据 = *DEF_引用插座数据(f_get输入插座(1), 0);

	float32 半径范围 = DEF_F32插座数据(f_get输入插座(2), 0);
	vec3 域大小 = DEF_Vec3插座数据(f_get输入插座(3), 0);
	vec3 域偏移 = DEF_Vec3插座数据(f_get输入插座(4), 0);



	auto 八叉树 = DEF_点距八叉树插座Value(f_get输出插座(1), 0);

	f_空间划分_remove所有子集(八叉树);
	f_空间划分_set叉树空间大小(八叉树, 域大小.x, 域偏移);
	switch (输入数据.m_Type) {
	case E_值类型::e_Type_Vec2: {

		break;
	}

	case E_值类型::e_Type_Vec3: {

		break;
	}

	case E_值类型::e_Type_Vec2_Array1D: {

		break;
	}

	case E_值类型::e_Type_Vec3_Array1D: {
		auto vec = *((std::vector<vec3>*)输入数据.m_Data);
		uint32 num = vec.size();
		auto* data = vec.data();
		for (uint32 i = 0; i < num; ++i) {
			f_空间划分_add子集(八叉树, data[i], 半径范围, nullptr);
		}

		std::vector<vec4> 生成的坐标;
		f_空间划分_解析为坐标(八叉树, 生成的坐标);
		f_surface_fill顶点数据(f_ob_fromMesh(m_Ob), 生成的坐标);
		break;

	}
	
	case E_值类型::e_Type_Object: {
		auto* inData = DEF_引用转物体(输入数据);
		S_Mesh* mesh = f_ob_fromMesh(inData);

		std::vector<S_VecSphere> 包围盒;
		f_surface_计算三角形球体包围盒(mesh, 包围盒);

		f_网格面树数据构建(包围盒, 八叉树);
		八叉树->m_映射的数据 = mesh;
		break;
	}

	case E_值类型::e_Type_Object_Array1D: {
		auto inData = ((std::vector<S_物体*>*)输入数据.m_Data);
		std::vector<S_Mesh*> meshs;
		f_提取物体中网格数据(*inData, meshs);

		uint32 num = meshs.size();

		S_Mesh* mesh = f_ob_fromMesh(m_Ob);
		f_surface_合并(meshs, *mesh);

		std::vector<S_VecSphere> 包围盒;
		f_surface_计算三角形球体包围盒(mesh, 包围盒);

		f_空间划分_从坐标索引(八叉树, 包围盒);
		//f_网格面树数据构建(包围盒, 八叉树);
		八叉树->m_映射的数据 = mesh;
		break;
	}

	case E_值类型::e_Type_Mesh: {
		auto* inData = DEF_引用转MESH(输入数据);

		std::vector<S_VecSphere> 包围盒;
		f_surface_计算三角形球体包围盒(inData, 包围盒);

		f_空间划分_从坐标索引(八叉树, 包围盒);
		//f_网格面树数据构建(包围盒, 八叉树);
		//八叉树->m_映射的数据 = inData.m_GPU网格;
		//八叉树->m_映射的数据类型 = E_值类型::e_Type_Mesh;
		break;
	}
	default:
		break;
	}



	return false;
}

void C_点距八叉树节点::f_网格面树数据构建(const std::vector<S_VecSphere>& 包围盒, S_点距八叉树* tree) {
	auto* box = 包围盒.data();
	uint32 num = 包围盒.size();

	for (uint32 三角形面索引 = 0; 三角形面索引 < num; ++三角形面索引) {
		auto* 单元 = f_空间划分_add子集(tree, box[三角形面索引].pos, box[三角形面索引].radius);
		if (单元->m_数据 == nullptr) {
			单元->m_数据 = new std::vector<uint32>();
		}
		((std::vector<uint32>*)单元->m_数据)->push_back(三角形面索引);
	}

	tree->m_映射的数据类型 = E_值类型::e_Type_UI32_1D;
}

S_物体* C_点距八叉树节点::f_get虚拟体() {
	return m_Ob;
}

void C_点距八叉树节点::f_入回收() {
	assert(m_Ob);
	f_NodeCtx_get默认场景()->f_remove物体(m_Ob, E_场景物体容器类型::e_集合);
}

void C_点距八叉树节点::f_回收() {
	f_NodeCtx_get默认场景()->f_add物体({ m_Ob }, E_场景物体容器类型::e_集合);
}

C_节点基类* f_node_载入点距八叉树节点(S_设备环境& ctx, FILE* f) {
	//float32 半径范围;
	//fread(&半径范围, sizeof(float32), 1, f);
	C_点距八叉树节点* node = new C_点距八叉树节点(ctx);
	//fread(&node->m_半径范围, sizeof(float32), 1, f);

	return node;
}

void f_node_保存点距八叉树节点(C_节点基类* n, FILE* f) {
	C_点距八叉树节点* node = dynamic_cast<C_点距八叉树节点*>(n);

	//fwrite(&node->m_半径范围, sizeof(float32), 1, f);
}
